package cn.minhx.domain.strategy.service.rule.chain.factory;

import cn.minhx.domain.strategy.model.entity.StrategyEntity;
import cn.minhx.domain.strategy.repository.IStrategyRepository;
import cn.minhx.domain.strategy.service.rule.chain.ILogicChain;
import lombok.*;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 抽奖责任链工厂
 *
 * @author min
 */
@Service
public class DefaultChainFactory {

    private final ApplicationContext applicationContext;
    private final IStrategyRepository repository;
    // 存放策略链，策略ID -> 责任链
    private final Map<Long, ILogicChain> strategyChainGroup;

    public DefaultChainFactory(ApplicationContext applicationContext, IStrategyRepository repository) {
        this.applicationContext = applicationContext;
        this.repository = repository;
        this.strategyChainGroup = new ConcurrentHashMap<>();
    }

    /**
     * 通过策略ID，构建责任链
     *
     * @param strategyId 策略ID
     * @return chain
     */
    public ILogicChain openLogicChain(Long strategyId) {
        ILogicChain cacheChain = strategyChainGroup.get(strategyId);
        if (null != cacheChain) {
            return cacheChain;
        }
        return assembleCacheAndGet(strategyId);
    }

    private ILogicChain assembleCacheAndGet(Long strategyId) {
        StrategyEntity strategy = repository.queryStrategyEntityByStrategyId(strategyId);
        String[] ruleModelArr = strategy.ruleModelArr();

        // 如果未配置抽奖模型，只需要设置默认随机抽奖
        if (null == ruleModelArr || 0 == ruleModelArr.length) {
            ILogicChain chain = applicationContext.getBean(LogicModel.RULE_DEFAULT.getCode(), ILogicChain.class);
            // 写入缓存
            strategyChainGroup.put(strategyId, chain);
            return chain;
        }

        // 按照配置的顺序装填【从redis缓存中获取，如果更新数据库，需要处理缓存数据】
        // 先获取第一个
        ILogicChain head = applicationContext.getBean(ruleModelArr[0], ILogicChain.class);
        ILogicChain current = head;
        for (int i = 1; i < ruleModelArr.length; i++) {
            ILogicChain next = applicationContext.getBean(ruleModelArr[i], ILogicChain.class);
            current = current.appendNext(next);
        }
        // 装填最后一个默认随机抽奖
        current.appendNext(applicationContext.getBean(LogicModel.RULE_DEFAULT.getCode(), ILogicChain.class));
        // 写入缓存
        strategyChainGroup.put(strategyId, head);

        return head;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class StrategyAwardVO {
        /** 抽奖奖品ID - 内部流转使用 */
        private Long awardId;
        /**  */
        private String logicModel;
    }


    @Getter
    @AllArgsConstructor
    public enum LogicModel {

        RULE_DEFAULT("rule_default", "默认抽奖"),
        RULE_BLACKLIST("rule_blacklist", "黑名单抽奖"),
        RULE_WEIGHT("rule_weight", "权重规则"),
        ;

        private final String code;
        private final String info;

    }

}